package com.powerbank.common.mq.transaction;

import com.powerbank.common.event.BaseEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 事务消息管理器
 * 提供分布式事务消息的统一管理
 */
@Slf4j
@Component
public class TransactionMessageManager {

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送支付事务消息
     */
    public void sendPaymentTransactionMessage(BaseEvent event, String paymentNo) {
        try {
            String destination = "PowerBank-Payment-Topic:" + event.getEventType();
            
            Message<BaseEvent> message = MessageBuilder
                    .withPayload(event)
                    .setHeader("eventId", event.getEventId())
                    .setHeader("eventType", event.getEventType())
                    .setHeader("paymentNo", paymentNo)
                    .setHeader("sourceService", event.getSourceService())
                    .build();
            
            log.info("发送支付事务消息: destination={}, paymentNo={}, eventId={}", 
                    destination, paymentNo, event.getEventId());
            
            rocketMQTemplate.sendMessageInTransaction(destination, message, paymentNo);
            
        } catch (Exception e) {
            log.error("发送支付事务消息失败: paymentNo={}, eventId={}", 
                     paymentNo, event.getEventId(), e);
            throw new RuntimeException("支付事务消息发送失败", e);
        }
    }

    /**
     * 发送订单事务消息
     */
    public void sendOrderTransactionMessage(BaseEvent event, Long orderId) {
        try {
            String destination = "PowerBank-Order-Topic:" + event.getEventType();
            
            Message<BaseEvent> message = MessageBuilder
                    .withPayload(event)
                    .setHeader("eventId", event.getEventId())
                    .setHeader("eventType", event.getEventType())
                    .setHeader("orderId", orderId)
                    .setHeader("sourceService", event.getSourceService())
                    .build();
            
            log.info("发送订单事务消息: destination={}, orderId={}, eventId={}", 
                    destination, orderId, event.getEventId());
            
            rocketMQTemplate.sendMessageInTransaction(destination, message, orderId);
            
        } catch (Exception e) {
            log.error("发送订单事务消息失败: orderId={}, eventId={}", 
                     orderId, event.getEventId(), e);
            throw new RuntimeException("订单事务消息发送失败", e);
        }
    }

    /**
     * 发送钱包事务消息
     */
    @Transactional(rollbackFor = Exception.class)
    public void sendWalletTransactionMessage(BaseEvent event, Long userId, String transactionNo) {
        try {
            String destination = "PowerBank-Payment-Topic:" + event.getEventType();
            
            Message<BaseEvent> message = MessageBuilder
                    .withPayload(event)
                    .setHeader("eventId", event.getEventId())
                    .setHeader("eventType", event.getEventType())
                    .setHeader("userId", userId)
                    .setHeader("transactionNo", transactionNo)
                    .setHeader("sourceService", event.getSourceService())
                    .build();
            
            log.info("发送钱包事务消息: destination={}, userId={}, transactionNo={}, eventId={}", 
                    destination, userId, transactionNo, event.getEventId());
            
            rocketMQTemplate.sendMessageInTransaction(destination, message, transactionNo);
            
        } catch (Exception e) {
            log.error("发送钱包事务消息失败: userId={}, transactionNo={}, eventId={}", 
                     userId, transactionNo, event.getEventId(), e);
            throw new RuntimeException("钱包事务消息发送失败", e);
        }
    }

    /**
     * 发送设备状态事务消息
     */
    public void sendDeviceTransactionMessage(BaseEvent event, String deviceCode) {
        try {
            String destination = "PowerBank-Device-Topic:" + event.getEventType();
            
            Message<BaseEvent> message = MessageBuilder
                    .withPayload(event)
                    .setHeader("eventId", event.getEventId())
                    .setHeader("eventType", event.getEventType())
                    .setHeader("deviceCode", deviceCode)
                    .setHeader("sourceService", event.getSourceService())
                    .build();
            
            log.info("发送设备状态事务消息: destination={}, deviceCode={}, eventId={}", 
                    destination, deviceCode, event.getEventId());
            
            rocketMQTemplate.sendMessageInTransaction(destination, message, deviceCode);
            
        } catch (Exception e) {
            log.error("发送设备状态事务消息失败: deviceCode={}, eventId={}", 
                     deviceCode, event.getEventId(), e);
            throw new RuntimeException("设备状态事务消息发送失败", e);
        }
    }

    /**
     * 批量发送事务消息
     */
    public void sendBatchTransactionMessages(String topic, BaseEvent[] events, Object[] args) {
        if (events.length != args.length) {
            throw new IllegalArgumentException("事件数组和参数数组长度必须相同");
        }
        
        try {
            for (int i = 0; i < events.length; i++) {
                BaseEvent event = events[i];
                Object arg = args[i];
                
                String destination = topic + ":" + event.getEventType();
                
                Message<BaseEvent> message = MessageBuilder
                        .withPayload(event)
                        .setHeader("eventId", event.getEventId())
                        .setHeader("eventType", event.getEventType())
                        .setHeader("batchIndex", i)
                        .setHeader("sourceService", event.getSourceService())
                        .build();
                
                rocketMQTemplate.sendMessageInTransaction(destination, message, arg);
                
                log.info("批量发送事务消息: destination={}, index={}, eventId={}", 
                        destination, i, event.getEventId());
            }
            
        } catch (Exception e) {
            log.error("批量发送事务消息失败: topic={}", topic, e);
            throw new RuntimeException("批量事务消息发送失败", e);
        }
    }
}